#include "GameState.h"
#include "../Core/CoreGlobals.h"
#include "../Render/RenderState.h"
#include "../Utils/LogUtil.h"
#include "Scene/GameScene.h"
#include "../Core/MaggotApp.h"

GameState::GameState()
{
	mFrameIndex = 0;
	mFrameCount = 0;
	mFrameAmount = 0;
}

GameState::~GameState()
{
	for (uint32 i = 0; i < mFrameCount; ++i)
	{
		CloseHandle(mFrameEvents[i]);
	}
	mFrameEvents.clear();
}

void GameState::Init()
{
	assert(GRenderState != nullptr);

	// mGameScene = new GameScene();
	mGameScene = MaggotApp::Get().CreateGameScene();
	mGameScene->Init();

	mGameTimer.Reset();

	// the frameCount is the same as rednerstate and imageCount
	mFrameCount = GRenderState->GetFrameCount();

	// create event for frame
	mFrameEvents.resize(mFrameCount);
	for (uint32 i = 0; i < mFrameCount; ++i)
	{
		mFrameEvents[i] = CreateEvent(nullptr, false, 0, nullptr);
		assert(mFrameEvents[i] != nullptr);
		ResetEvent(mFrameEvents[i]);
	}
}

void GameState::WaitForRender()
{
	// wait current frame until render unlock
	WaitForSingleObject(GRenderState->GetFrameEvent(mFrameIndex), INFINITE);

	// lock next frame
	ResetEvent(mFrameEvents[mFrameIndex]);

	// LOGI(L"Game   Frame %d -> %lld", mFrameIndex, mFrameAmount);
}

void GameState::MainLoop()
{
	mGameTimer.Tick();
	mGameScene->Tick(mGameTimer.GetDeltaTime());
}

void GameState::NextFrame()
{
	// unlock pre frame
	SetEvent(mFrameEvents[mFrameIndex]);
	mFrameIndex = (mFrameIndex + 1) % mFrameCount;
	mFrameAmount++;
}

void GameState::Stop()
{
	for (uint32 i = 0; i < mFrameCount; ++i)
	{
		SetEvent(mFrameEvents[i]);
	}
}

void GameState::Exit()
{
	mGameScene->Exit();
	MaggotApp::Get().DeleteGameScene(mGameScene);
}

uint32 GameState::GetFrameIndex() const
{
	return mFrameIndex;
}

uint32 GameState::GetFrameCount() const
{
	return mFrameCount;
}

uint64 GameState::GetFrameAmount() const
{
	return mFrameAmount;
}

HANDLE GameState::GetFrameEvent(uint32 index)
{
	return mFrameEvents[index];
}

GameScene* GameState::GetGameScene() const
{
	return mGameScene;
}
